import React, { useEffect, useRef, useState } from 'react'
import styles from './index.module.scss'
import { Tag, Form, Input, Button, message, Upload, Space } from 'antd'
import type { RcFile, UploadFile } from 'antd/es/upload/interface'
import { useAppDispatch, useAppSelector } from '@/store'
import { set_active_topic } from '@/store/slice/subject'
import { select_active_topic, select_subject_two_active } from '@/store/slice/subject/select'
import { get_topic_list_async } from '@/store/slice/subject/request'
import { cancelChunkUpload, chunks_upload_cancel, getMd5Exist, getMerge, patchTopic, postTopic, postUploadChunk } from '@/util/request'
import YuUpload from '@/common_components/upload'
import { imgUrl, VIDEO_URL } from '@/util/constant'
import type { UploadProps } from 'antd'
import { UploadOutlined } from '@ant-design/icons'
import { sliceChunks, CHUNK_SIZE, webWorkerHash } from '@/util/file_silce'
import type { UploadRequestOption, UploadProgressEvent } from 'rc-upload/lib/interface'

type FieldType = {
  title?: string
  dec?: string
  img: string
  video: string
  reference: string
}

// 题目详情
export default function TopicDetail() {
  const dispatch = useAppDispatch()
  const [form] = Form.useForm()
  const [messageApi, contextHolder] = message.useMessage()
  // upload的状态
  const [fileList, setFileList] = useState<UploadFile[]>([])

  //upload的 视频列表
  const [videoFileList, setVideoFileList] = useState<UploadFile[]>([])

  // 设置视频的url
  const [videoUrl, setVideoUrl] = useState('')

  // 上传进度
  const percent = useRef(0)

  // 获取当前选中的题目,该选中的题目是通过列表组件点击的
  const active_topic = useAppSelector(select_active_topic)
  // 获取当前选中的二级课程
  const active_subject_two = useAppSelector(select_subject_two_active)

  useEffect(() => {
    console.log('============修改')
    // 如果不存在选中的题目则清空表格内容，因为点击新增题目的时候会清空选中的题目信息
    if (!active_topic) {
      reset()
      setVideoFileList([])
    } else {
      // 设置表单的回显
      form.setFieldsValue(active_topic)

      const topic_img = active_topic.img
      const video = active_topic?.video

      // 判断是否为'' 如果是则说明没有图片
      if (topic_img) {
        setFileList([
          {
            uid: topic_img,
            name: topic_img,
            status: 'done',
            url: imgUrl + topic_img
          }
        ])
      } else {
        setFileList([])
      }

      // 如果改题目没有视频，则不显示视频名字
      if (video) {
        setVideoUrl(VIDEO_URL + video)

        setVideoFileList([
          {
            uid: video,
            name: video.split('/')[3],
            status: 'done'
          }
        ])
      } else {
        setVideoFileList([])
      }
    }
  }, [active_topic])

  // 保存题目
  const onFinish = async (values: any) => {
    const { video } = values

    const new_values = { ...values, img: fileList[0]?.uid, video: video?.file?.response.path }
    console.log(new_values)

    //根据题目的属性里面有没有选中的ID来判断是更新还是新增
    if (active_topic?.hasOwnProperty('_id')) {
      const res = await patchTopic(active_topic._id, { ...new_values })

      if (res.status === 200) {
        messageApi.success('修改成功')
      }
      // 新增
    } else {
      const res = await postTopic({ ...new_values, two_id: active_subject_two.value })

      if (res.status === 201) {
        messageApi.success('新增成功')
        reset()
      }
    }
    // 获取题目列表
    dispatch(get_topic_list_async(active_subject_two.value))
  }

  // 提交失败
  const onFinishFailed = (errorInfo: any) => {
    messageApi.open({
      type: 'warning',
      content: '你还有未填写信息'
    })
  }

  // 处理图片改变
  const uploadChange = (fileList: UploadFile[]) => {
    setFileList(fileList)
  }

  // 重置表单清空数据
  const reset = (): any => {
    form.resetFields()
    setFileList([])
  }

  // ==========================================
  // 上传视频

  // 上传分片====通过promise.all一起发送,优化网路发送时间
  const uploadChunk = (chunks: Blob[], md5: string, uploaded_chunk_list: any[], onProgress: any) => {
    // 上传总数量====用于记录上传进度
    const total = chunks.length

    // 用于并发上传=====Promise.all
    const promise_chunk_list = [] as any[]

    chunks.forEach((item: Blob, index: number) => {
      // 如果在已经上传的chunks中没找到，说明是未上传的
      if (uploaded_chunk_list.indexOf(index) === -1) {
        // 通过FormData传递Blob类型数据
        // FormData 对象主要用于模拟 HTML 表单数据，
        // 它可以方便地处理表单数据的收集、编码和发送，常用于与服务器进行数据交互，特别是在处理文件上传和表单提交时非常有用。
        const form = new FormData()

        form.append('chunk', chunks[index])
        // append的value类型只能为string或者Blob
        form.append('index', index + '')
        form.append('md5', md5)
        form.append('total', total + '')

        promise_chunk_list.push(postUploadChunk(form))
      }
    })

    // 上传进度显示====监听promise.all的请求进度
    promise_chunk_list.forEach(item => {
      item.then((res: any) => {
        // rest是后端返回的数据
        const rest = res?.data?.data.rest
        // 因为点击暂停请求后====后续的都没有数据为 NAN
        if (rest) {
          // ====此处主要是为了点击暂停时用的
          // 计算百分比
          percent.current = Math.ceil(((total - rest) / total) * 100)
          onProgress && onProgress({ percent: Math.ceil(((total - rest) / total) * 100) })
        }
      })
    })

    return new Promise((resolve, reject) => {
      Promise.all(promise_chunk_list).then(res_list => {
        // chunks是否还有未上传的
        const none_flag = res_list.some(res => {
          const rest = res?.data?.data.rest
          if (rest === 0) {
            return true
          }
        })

        // 如果全部上传完毕返回true
        if (none_flag) {
          resolve(true)
        } else {
          resolve(false)
        }
      })
    })
  }

  // 暂停上传
  const stopUpload = () => {
    cancelChunkUpload()
  }

  const videoProps: UploadProps = {
    name: 'video',
    withCredentials: true,
    maxCount: 1,
    accept: 'video/mp4',
    fileList: videoFileList,
    onChange(info) {
      if (info.file.status == 'uploading') {
        // message.success(`${info.file.name} 正在上传中`)
      }
      if (info.file.status === 'done') {
        message.success(`${info.file.name} 视频上传成功`)
      } else if (info.file.status === 'error') {
        message.error(`${info.file.name} 暂停上传`)
      }

      setVideoFileList([info.file])
    },
    onRemove() {
      setVideoFileList([])
      return false
    },
    async customRequest({ file, onSuccess, onError, onProgress }: UploadRequestOption) {
      try {
        // 点击暂停后,再次上传文件需要显示之前的进度
        onProgress && onProgress({ percent: percent.current })

        const name = (file as RcFile).name.split('.')[0]
        // 获得分片数组
        const chunks = sliceChunks(file as RcFile)

        // 获取整个文件的hash====使用了增量计算，web worker开启多线程
        const md5 = (await webWorkerHash(chunks)) as string

        // 检查视频是否已经上传过了=====上传过就秒传
        const { data: uploade_res } = await getMd5Exist(md5, name)

        // 是否快传
        const is_exist = uploade_res?.data.is_exist

        // 已经上传过的分片
        const uploaded_chunk_list = uploade_res?.data.chunkList

        // 如果不存在========断点续传
        if (!is_exist) {
          // 是否全部上传完毕
          const is_all_upload = (await uploadChunk(chunks, md5, uploaded_chunk_list, onProgress)) as number

          // 如果全部上传完毕，剩余要上传的片数为0=======调用合并接口
          if (is_all_upload) {
            // 合并分片
            const { data: merge_res } = await getMerge(md5, name, chunks.length, CHUNK_SIZE)
            setVideoUrl(VIDEO_URL + merge_res.data.path)
            onSuccess && onSuccess(merge_res.data)
          } else {
            console.log(percent.current)
            // 如果点击暂停后====显示进度条
            onProgress && onProgress({ percent: percent.current })
          }
        } else {
          setVideoUrl(VIDEO_URL + uploade_res?.data.path)
          // 秒传
          onSuccess && onSuccess(uploade_res?.data)
        }
      } catch (error: any) {
        onError && onError(error)
      }
    }
  }

  return (
    <div className={styles.detail}>
      {contextHolder}
      <div className={styles.header}>
        <span className={styles.name}>题目详情</span>
        {active_topic?.hasOwnProperty('_id') ? <Tag color="warning">修改</Tag> : <Tag color="success">新增</Tag>}
      </div>
      <div className={styles.form}>
        <Form name="basic" form={form} initialValues={{ remember: true }} onFinish={onFinish} onFinishFailed={onFinishFailed} autoComplete="off">
          <Form.Item<FieldType> label="题干:" name="title" rules={[{ required: true, message: '请输入题干!' }]}>
            <Input />
          </Form.Item>

          <Form.Item<FieldType> label="描述:" name="dec" rules={[{ required: true, message: '请输入描述!' }]}>
            <Input.TextArea />
          </Form.Item>

          <Form.Item<FieldType> label="参考答案:" name="reference" rules={[{ required: true, message: '请输入参考答案!' }]}>
            <Input.TextArea />
          </Form.Item>

          <Form.Item<FieldType> style={{ marginBottom: 5 }} label="图片:" name="img">
            <YuUpload sort="topic" fileList={fileList} onChange={uploadChange}></YuUpload>
          </Form.Item>

          <Space>
            <Form.Item<FieldType> style={{ marginBottom: 10 }} label="视频:" name="video">
              <Upload {...videoProps}>
                <Button icon={<UploadOutlined />}>点击上传视频</Button>
              </Upload>
            </Form.Item>

            <Button style={{ marginLeft: 50, marginBottom: 10 }} type="primary" danger onClick={stopUpload}>
              暂停上传
            </Button>

            <Form.Item style={{ marginTop: 10, marginLeft: 100 }} wrapperCol={{ span: 16 }}>
              <Button type="primary" htmlType="submit">
                保存题目
              </Button>
            </Form.Item>
          </Space>
        </Form>

        {active_topic?.video ? <video className={styles.video} src={videoUrl} controls={true} /> : null}
      </div>
    </div>
  )
}
